package com.kede.api.stand.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.kede.api.stand.service.CertiService;
import com.kede.api.stand.service.IUserManageService;
import com.kede.api.stand.utils.GaoDeMapUtil;
import com.kede.dictenum.BoolDictEnum;
import com.kede.domain.ConfigDomain;
import com.kede.domain.ZhiOrderDomain;
import com.kede.domain.ZhiOrderGoodsListDomain;
import com.kede.domain.ZhiUserCertifiedDomain;
import com.kede.ienum.order.CertiTypeEnum;
import com.kede.ienum.store.CertiStatueEnum;
import com.kede.ienum.zhi.ZhiOrderTypeEnum;
import com.kede.pojo.ResHttp;
import com.kede.pojo.ZhiTypeEnum;
import com.kede.service.ConfigService;
import com.kede.service.ZhiOrderGoodsListService;
import com.kede.service.ZhiOrderService;
import com.kede.service.ZhiUserCertifiedService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/***
 ** @Author:Pr.li
 ** @Description:
 ** @Date: create in 2023/6/1 16:53
 ***/
@Service
public class CertiServiceImpl implements CertiService {

    @Resource
    private ZhiUserCertifiedService userCertifiedService;

    @Resource
    private IUserManageService userManageService;

    @Resource
    private ZhiOrderService zhiOrderService;

    @Resource
    private ConfigService configService;

    @Resource
    private ZhiOrderGoodsListService zhiOrderGoodsListService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResHttp storeCertified(ZhiUserCertifiedDomain certifiedDomain) {
        //查询认证状态
        LambdaQueryWrapper<ZhiUserCertifiedDomain> queryWrapper = new LambdaQueryWrapper<>();
        CertiTypeEnum certiTypeEnum = CertiTypeEnum.parse(certifiedDomain.getType());
        queryWrapper.eq(ZhiUserCertifiedDomain::getType,certifiedDomain.getType());
        queryWrapper.eq(ZhiUserCertifiedDomain::getUserId,certifiedDomain.getUserId());
        ZhiUserCertifiedDomain one = userCertifiedService.getOne(queryWrapper);
        if (ObjectUtil.isNull(one)){
            certifiedDomain.setIsPay(BoolDictEnum.FALSE.getCode());
            String sn = OrderRandomNo();
            certifiedDomain.setOrderSn(sn);
            BigDecimal cerMoney = getCerMoney(certiTypeEnum);
            certifiedDomain.setMoney(cerMoney);
            GaoDeMapUtil.AddressComponentDto addressComponentDto = GaoDeMapUtil.getAddressComponentByLocation(certifiedDomain.getLng(), certifiedDomain.getLat());
            certifiedDomain.setSheng(addressComponentDto.getProvince());
            certifiedDomain.setShi(addressComponentDto.getCity());
            certifiedDomain.setQu(addressComponentDto.getDistrict());
            certifiedDomain.setAreaCode(addressComponentDto.getAdcode());
            certifiedDomain.setStatus(CertiStatueEnum.REVIEW);
            Long now = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8));
            certifiedDomain.setCreatetime(now.intValue());
            boolean save = userCertifiedService.save(certifiedDomain);
            ZhiOrderDomain zhiOrderDomain = new ZhiOrderDomain();
            zhiOrderDomain.setOrderSn(sn);
            zhiOrderDomain.setUserId(certifiedDomain.getUserId());
            zhiOrderDomain.setCertifiedId(certifiedDomain.getId());
            zhiOrderDomain.setCreatetime(now.intValue());
            zhiOrderDomain.setOrderMoney(cerMoney);
            zhiOrderDomain.setOrderType(ZhiOrderTypeEnum.CERTI);
            zhiOrderService.save(zhiOrderDomain);
            Map<String ,Object> map = new HashMap<>();
            map.put("orderSn",sn);
            map.put("orderMoney",cerMoney);
            return ResHttp.set(2001,"提交认证成功",map);
            //下面复杂 包含幂等性判断
        }else if(one.getIsPay().equals(BoolDictEnum.FALSE.getCode())){
            //未付款
            return ResHttp.set(2002,"审核未支付",one);
        }else if(one.getIsPay().equals(BoolDictEnum.TRUE.getCode())){
            CertiStatueEnum status = one.getStatus();
            switch (status){
                case REVIEW:
                    return ResHttp.set(2000,"审核中",one);
                case REFUSE:
                    one.setStatus(CertiStatueEnum.REVIEW);
                    Long l = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8));
                    one.setUpdatetime(l.intValue());
                    if (!certifiedDomain.getLng().equals("0") && !certifiedDomain.getLat().equals("0")){
                        GaoDeMapUtil.AddressComponentDto addressComponentDto = GaoDeMapUtil.getAddressComponentByLocation(certifiedDomain.getLng(), certifiedDomain.getLat());
                        one.setSheng(addressComponentDto.getProvince());
                        one.setShi(addressComponentDto.getCity());
                        one.setQu(addressComponentDto.getDistrict());
                        one.setAreaCode(addressComponentDto.getAdcode());
                    }
                    userCertifiedService.updateById(one);
                    return ResHttp.set(2000,"审核已重新提交申请",new ArrayList<>());
                case APPROVED:
                    return ResHttp.set(2000,"审核已通过",one);
            }
        }
        return ResHttp.set(2001,"提交认证失败",null);
    }


    /**
     * 置换时获取门店列表
     * @param lng
     * @param lat
     * @param keyword
     * @param type  1为现金  0为德币
     * @return
     */
    @Override
    public ResHttp storeList(String lng, String lat, String keyword, Integer type,
                             Integer userId, Integer goodsCount) {
        if(StrUtil.isBlank(lng) || StrUtil.isBlank(lat)){
           return ResHttp.set(2001,"请先开启定位权限",new ArrayList<>());
        }
        ConfigDomain old_unit_num = null;
        LambdaQueryWrapper<ZhiUserCertifiedDomain> queryWrapper = new LambdaQueryWrapper<>();
        Integer adcode = GaoDeMapUtil.getAddressComponentByLocation(lng, lat).getAdcode();
        queryWrapper.eq(ZhiUserCertifiedDomain::getAreaCode,adcode);
        queryWrapper.eq(ZhiUserCertifiedDomain::getType,CertiTypeEnum.STORE.getCode());
        queryWrapper.eq(ZhiUserCertifiedDomain::getStatus,CertiStatueEnum.APPROVED.getEnumIndex());
        if(type.equals(ZhiTypeEnum.DEBIWEIGHT.getCode())){
            //称斤就正常查询没有特殊设置
        }else if(type.equals(ZhiTypeEnum.MONEY.getCode())){
            queryWrapper.eq(ZhiUserCertifiedDomain::getEnableZhiMoney,BoolDictEnum.TRUE.getCode());
            //获取旧的门店现金置换数
            old_unit_num = configService.getOneByName("old_money_unit_num");
        }else{
            //获取旧的门店德币置换数
            old_unit_num = configService.getOneByName("old_unit_num");
        }
        if (StrUtil.isNotBlank(keyword)){
            queryWrapper.like(ZhiUserCertifiedDomain::getStoreName,keyword);
        }
        queryWrapper.select(ZhiUserCertifiedDomain::getZhizhaoimage,ZhiUserCertifiedDomain::getAddress,ZhiUserCertifiedDomain::getStoreName,ZhiUserCertifiedDomain::getUserId,ZhiUserCertifiedDomain::getIsWork,ZhiUserCertifiedDomain::getLng,ZhiUserCertifiedDomain::getLat,ZhiUserCertifiedDomain::getEnableUserUpload);
        List<ZhiUserCertifiedDomain> list = userCertifiedService.list(queryWrapper);
        if (userId == null){
            return ResHttp.okData(list);
        }
        for (ZhiUserCertifiedDomain certifiedDomain : list) {
            //如果门店没有开启 用户无限上传的功能
            if (old_unit_num != null &&certifiedDomain.getEnableUserUpload().equals(BoolDictEnum.FALSE.getCode())){
                //查这个用户在这个门店换了衣服的数量
                LambdaQueryWrapper<ZhiOrderGoodsListDomain> goodWrapper = new LambdaQueryWrapper<>();
                goodWrapper.eq(ZhiOrderGoodsListDomain::getUserId,userId);
                goodWrapper.eq(ZhiOrderGoodsListDomain::getStoreId,certifiedDomain.getUserId());
                int count = userManageService.getCountZhiOrderGooded(goodWrapper);
                int limit = Integer.valueOf(old_unit_num.getValue());
                int canUpCount = limit - count;
                certifiedDomain.setZhiCurCount(count);
                certifiedDomain.setZhiLimitCount(limit);
                if(canUpCount <= 0 || goodsCount > canUpCount){
                    certifiedDomain.setZhiCanSlielectStore(BoolDictEnum.FALSE.getCode());
                }
            }
            double v = GaoDeMapUtil.GetDistance(Double.valueOf(lng), Double.valueOf(lat), Double.valueOf(certifiedDomain.getLng()), Double.valueOf(certifiedDomain.getLat()));
            certifiedDomain.setDistance(String.valueOf(v));
        }
        return ResHttp.okData(list);
    }

    @Override
    public ResHttp getCertifiInfo(Integer storeUserId) {
        LambdaQueryWrapper<ZhiUserCertifiedDomain> queryWrapper = new LambdaQueryWrapper<>();
        ZhiUserCertifiedDomain oneByUserId = userCertifiedService.getOneByUserId(storeUserId);
        return ResHttp.okData(oneByUserId);
    }

    public static String OrderRandomNo(){
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder
                .append("CER")//不要改php的支付回调对这个开头的订单有处理
                .append(DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmm"))
                .append(RandomUtil.randomNumbers(4));
        return stringBuilder.toString();
    }

    public BigDecimal getCerMoney(CertiTypeEnum certiTypeEnum){
        LambdaQueryWrapper<ConfigDomain> queryWrapper = new LambdaQueryWrapper<>();
        switch (certiTypeEnum){
            case STORE:
                queryWrapper.eq(ConfigDomain::getName,"cer_money");
                break;
            case QUDAI:
                queryWrapper.eq(ConfigDomain::getName,"qu_cer_money");
                break;
            case SHIDAI:
                queryWrapper.eq(ConfigDomain::getName,"shi_cer_money");
                break;
        }

        ConfigDomain one = configService.getOne(queryWrapper);
        if (ObjectUtil.isNull(one)){
            throw new RuntimeException("查询认证金额出错");
        }else {
            return new BigDecimal(one.getValue());
        }

    }

}
